package com.erp.freight.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.erp.freight.domain.*;
import com.erp.freight.domain.vo.AEProductRefinementFreightVo;
import com.erp.freight.domain.vo.ErpLogisticsServiceInfoVo;
import com.erp.freight.domain.vo.ErpProductRefinementFreightVo;
import com.erp.freight.mapper.*;
import com.erp.freight.service.IErpCommonProductFreightService;
import com.erp.freight.service.IErpProductFreightService;
import com.ruoyi.common.core.utils.bean.BeanCopyUtils;
import com.ruoyi.common.core.utils.oldUtils.StringUtils;
import com.ruoyi.freight.api.domain.AeProductFreight;
import com.ruoyi.freight.api.domain.ErpProductExistingFreightRecord;
import com.ruoyi.gather.api.domain.ErpProductArea64;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 公共运费试算、预估运费Service接口
 *
 * @author erp
 * @date 2023-07-20
 */
@RequiredArgsConstructor
@Service
public class ErpCommonProductFreightServiceImpl implements IErpCommonProductFreightService {

    private final IErpProductFreightService productFreightService;
    private final ErpProductFreightBaleMapper baleMapper;
    private final ErpProductFreightYanwenMapper yanwenMapper;
    private final ErpProductFreightMapper baseMapper;
    private final ErpProductFreightEconomyMapper economyMapper;
    private final ErpProductFreightCountryZoneMapper countryZoneMapper;
    private final ErpProductAreaMapper areaMapper;
    private final ErpProductArea64Mapper area64Mapper;
    private final ErpLogisticsServiceInfoMapper logisticsServiceInfoMapper;

    @Override
    public BigDecimal freightTrialByCaiNiao(ErpProductExistingFreightRecord productFreight) {
        return freightTrialByCaiNiao(productFreight, false);
    }

    @Override
    public BigDecimal freightTrialByCaiNiao(AeProductFreight productFreight) {
        return freightTrialByCaiNiao(productFreight, false);
    }

    /**
     * 以菜鸟运费计价模版为准进行运费试算
     *
     * @param productFreight
     * @param isSplit        是否是进行拆分试算
     * @return
     */
    @Override
    public BigDecimal freightTrialByCaiNiao(ErpProductExistingFreightRecord productFreight, Boolean isSplit) {
        // 是否是大包
        Boolean isBale = false;
        if (productFreight.getType().intValue() == 3) {
            // 设置的模版就是大包，则按大包进行计算
            isBale = true;
        } else {
            // 判断是否是大包
            isBale = productFreightService.judgeBaleProduct(productFreight);
        }
        // 是否为大包
        productFreight.setIsBale(isBale);
        // 是否为运费试算
        productFreight.setIsTrial(isSplit ? false : true);
        // 预估运费
        BigDecimal freight = new BigDecimal("1000");

        if (isBale) {
            // 大包，先计算大包专线
            productFreight.setFreightType("菜鸟大包专线");
            return freightCalculateByCainiaoHeavy(productFreight);
        } else if (productFreight.getType().intValue() == 0) {
            // 普货，计算标准普货
            productFreight.setFreightType("菜鸟无忧物流-标准");
            return freightCalculateByCainiaoStandard(productFreight);
        } else if (productFreight.getType().intValue() == 1) {
            // 计算特货专线-标准
            productFreight.setFreightType("菜鸟特货专线－标准");
            return freightCalculateByCainiaoStandard(productFreight);
        } else if (productFreight.getType().intValue() == 4) {
            // 经济普货
            productFreight.setFreightType("菜鸟超级经济Global");
            return freightCalculateByCainiaoSuperEconomy(productFreight);
        } else if (productFreight.getType().intValue() == 5) {
            // 经济特货
            productFreight.setFreightType("菜鸟特货专线－超级经济");
            return freightCalculateByCainiaoSuperEconomy(productFreight);
        } else {
            return freight;
        }

        /** 后期再用 **/
        // 大包，先计算大包专线
//			productFreight.setFreightType("菜鸟大包专线");
//			BigDecimal freightHeavy = freightCalculateByCainiaoHeavy(productFreight);
//			// 再计算标准-大包
//			productFreight.setFreightType("菜鸟无忧物流-标准");
//			freight = freightCalculateByCainiaoHeavy(productFreight);
//			// 标准大包和大包专线 取小
//			return freightHeavy.compareTo(freight) > 0 ? freight : freightHeavy;
        /** 后期再用 **/
        /** 后期再用 **/
//				// 普货，先计算标准普货
//				productFreight.setFreightType("菜鸟无忧物流-标准");
//				freight = freightCalculateByCainiaoStandard(productFreight);
//				// 再计算标准特货
//				productFreight.setType(1);
//				BigDecimal freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 标准和特货 取小
//				freight = freightSG.compareTo(freight) > 0 ? freight : freightSG;
//				// 再计算特货专线-标准
//				productFreight.setFreightType("菜鸟特货专线－标准");
//				freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 取小后，和特货专线 取小
//				return freightSG.compareTo(freight) > 0 ? freight : freightSG;
        /** 后期再用 **/
    }

    /**
     * 以菜鸟运费计价模版为准进行运费试算
     *
     * @param productFreight
     * @param isSplit        是否是进行拆分试算
     * @return
     */
    @Override
    public BigDecimal freightTrialByCaiNiao(AeProductFreight productFreight, Boolean isSplit) {
        // 是否是大包
        Boolean isBale = false;
        if (productFreight.getType().intValue() == 3) {
            // 设置的模版就是大包，则按大包进行计算
            isBale = true;
        } else {
            // 判断是否是大包
            isBale = productFreightService.judgeBaleProduct(productFreight);
        }
        // 是否为大包
        productFreight.setIsBale(isBale);
        // 是否为运费试算
        productFreight.setIsTrial(isSplit ? false : true);
        // 预估运费
        BigDecimal freight = new BigDecimal("1000");

        if (isBale) {
            // 大包，先计算大包专线
            productFreight.setFreightType("菜鸟大包专线");
            return freightCalculateByCainiaoHeavy(productFreight);
        } else if (productFreight.getType().intValue() == 0) {
            // 普货，计算标准普货
            productFreight.setFreightType("菜鸟无忧物流-标准");
            return freightCalculateByCainiaoStandard(productFreight);
        } else if (productFreight.getType().intValue() == 1) {
            // 计算特货专线-标准
            productFreight.setFreightType("菜鸟特货专线－标准");
            return freightCalculateByCainiaoStandard(productFreight);
        } else if (productFreight.getType().intValue() == 4) {
            // 经济普货
            productFreight.setFreightType("菜鸟超级经济Global");
            return freightCalculateByCainiaoSuperEconomy(productFreight);
        } else if (productFreight.getType().intValue() == 5) {
            // 经济特货
            productFreight.setFreightType("菜鸟特货专线－超级经济");
            return freightCalculateByCainiaoSuperEconomy(productFreight);
        } else {
            return freight;
        }

        /** 后期再用 **/
        // 大包，先计算大包专线
//			productFreight.setFreightType("菜鸟大包专线");
//			BigDecimal freightHeavy = freightCalculateByCainiaoHeavy(productFreight);
//			// 再计算标准-大包
//			productFreight.setFreightType("菜鸟无忧物流-标准");
//			freight = freightCalculateByCainiaoHeavy(productFreight);
//			// 标准大包和大包专线 取小
//			return freightHeavy.compareTo(freight) > 0 ? freight : freightHeavy;
        /** 后期再用 **/
        /** 后期再用 **/
//				// 普货，先计算标准普货
//				productFreight.setFreightType("菜鸟无忧物流-标准");
//				freight = freightCalculateByCainiaoStandard(productFreight);
//				// 再计算标准特货
//				productFreight.setType(1);
//				BigDecimal freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 标准和特货 取小
//				freight = freightSG.compareTo(freight) > 0 ? freight : freightSG;
//				// 再计算特货专线-标准
//				productFreight.setFreightType("菜鸟特货专线－标准");
//				freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 取小后，和特货专线 取小
//				return freightSG.compareTo(freight) > 0 ? freight : freightSG;
        /** 后期再用 **/
    }


    @Override
    public List<AeProductFreight> freightTrialWith64(@RequestBody AeProductFreight aeProductFreight) {
        List<AeProductFreight> productFreightList = new ArrayList<>();


        // 获取国家
        List<ErpProductArea64> selectList = area64Mapper.selectList();

        // 判断是哪种产品
        for (ErpProductArea64 erpProductArea : selectList) {
            AeProductFreight resultFreight = new AeProductFreight();
            BeanCopyUtils.copy(aeProductFreight, resultFreight);
            if (erpProductArea.getAreaNo().equals("GB")) {
//				erpProductArea.setAreaNo("UK");
            }
            if (erpProductArea.getAreaNo().equals("RUS")) {
                erpProductArea.setAreaNo("RU");
            }

            resultFreight.setCountry(erpProductArea.getAreaNo());

            BigDecimal calculateFreightByCaiNiao = freightTrialByCaiNiao(resultFreight);
            if (calculateFreightByCaiNiao != null) {
                resultFreight.setFreight(calculateFreightByCaiNiao);
//				resultFreight.setCountry(erpProductArea.getAreaName() + "(" + erpProductArea.getAreaNo() + ")");
                resultFreight.setCountry(erpProductArea.getAreaNo());
                productFreightList.add(resultFreight);
            } else {
//					// 运费试算失败
                continue;
            }
        }
        return productFreightList;
    }


    /**
     * 根据商品属性，获取推荐物流线路
     *
     * @param productFreight
     * @return
     */
    @Override
    public List<ErpLogisticsServiceInfoVo> getRecommendedLogisticsRoutes(ErpProductExistingFreightRecord productFreight) {
        List<ErpLogisticsServiceInfoVo> result = new ArrayList<>();
        ErpLogisticsServiceInfoVo vo;
        /**
         * 推荐线路规则 1、优先判断是否为大包，如果是大包，推荐大包路线：菜鸟无忧物流-标准、菜鸟大包专线、以及燕文相关
         * 2、判断是否为特货，如果是特货，推荐特货路线：菜鸟特货专线－超级经济、菜鸟特货专线－标准、燕文专线追踪-特货、燕文专线快递-特货
         * 3、否则为普货，推荐普货路线：除大包外的所有路线
         */
        // 获取物流线路
        List<ErpLogisticsServiceInfo> logisticsServiceInfoList = logisticsServiceInfoMapper
                .selectLogisticsServicesByTemplateValue(productFreight.getType() + "");

        // 判断是否是大包
        if (productFreight.getType().intValue() == 3) {
            productFreight.setType(null);
            // 是否为大包
            productFreight.setIsBale(true);
        } else {
            Boolean isBale = productFreightService.judgeBaleProduct(productFreight);
            if (isBale) {
                // 如果是大包，则修改试算类型
                productFreight.setType(null);
                // 是否为大包
                productFreight.setIsBale(true);
                logisticsServiceInfoList = logisticsServiceInfoMapper.selectLogisticsServicesByTemplateValue("3");
            }
        }

        // 是否为运费试算
        productFreight.setIsTrial(false);

        BigDecimal freight = new BigDecimal("0");
        for (ErpLogisticsServiceInfo logisticsServiceInfo : logisticsServiceInfoList) {
            vo = new ErpLogisticsServiceInfoVo();
            productFreight.setFreightType(logisticsServiceInfo.getLogisticsServiceName());
            if (logisticsServiceInfo.getLogisticsServiceName().contains("大包")) {
                freight = freightCalculateByCainiaoHeavy(productFreight);
            } else if (logisticsServiceInfo.getLogisticsServiceName().contains("经济")) {
                freight = freightCalculateByCainiaoSuperEconomy(productFreight);
            } else if (logisticsServiceInfo.getLogisticsServiceName().contains("燕文")) {
                freight = freightCalculateByYanWen(productFreight);
            } else {
                freight = freightCalculateByCainiaoStandard(productFreight);
            }
            if (freight != null && freight.compareTo(new BigDecimal("0")) > 0) {
                BeanUtil.copyProperties(logisticsServiceInfo, vo);
                vo.setFreight(freight.setScale(2, BigDecimal.ROUND_UP).toString());
                result.add(vo);
            }
        }
        return result;
    }

    /**
     * 计算精细化运费模版
     *
     * @param templateType          1-标准普货，2-经济普货，3-标准大包，4-大包专线，5-标准特货，6-经济特货，7-特货专线-标准
     * @param benchmarkTemplateType 基准模版，即我是否需要根据基准模版计算差值，可以为空
     * @param currency              USD 美元 RMB 人民币
     * @return
     */
    @Override
    public List<ErpProductRefinementFreightVo> calculateRefinementFreightTemplate(String templateType,
                                                                                  String benchmarkTemplateType, String currency) {
        List<ErpProductRefinementFreightVo> voList = new ArrayList<>();
        ErpProductRefinementFreightVo vo = null;
        Map<String, ErpProductRefinementFreightVo> voMap = new HashMap<>();

        // 1、按100g为一个区间，分别获取32个国家的最低运费
        // 获取区域调价国家
        List<ErpProductArea> erpProductAreaList = areaMapper.selectList();
        List<String> countryCode32List = erpProductAreaList.stream().map(e -> e.getAreaNo())
                .collect(Collectors.toList());

        // 记录上一轮的基准运费和真实运费 格式：key=countryCode, value=基准:真实
        Map<String, String> previousFreightMap = new HashMap<>();
        // 真实运费
        BigDecimal previousActual = new BigDecimal("0");
        // 基准运费
        BigDecimal previousBenchmark = new BigDecimal("0");

        // 获取所有国家
        List<ErpProductFreight> allCountryList = baseMapper.selectDistinctCountryCode();

        // 根据类型确定循环次数
        int cycles = (templateType.equals("3") || templateType.equals("4")) ? 200 : 20;
        // 根据模版类型确定起始数据 0=100g,10=100g,20=2000g
        int ii = 0;
        // 以每100g为一个区间做运费试算
        BigDecimal startWeight = new BigDecimal("100");
        // 计费模版为标准普通，说明基准模版为大包类，2kg以下无需计算 TODO 这里的判断有问题，先注释掉
//		if(templateType.equals("1")){
//			ii = 21;
//			startWeight = new BigDecimal("2000");
//		}

        for (int i = ii; i < cycles; i++) {
            // 区域调价国家最小值
            BigDecimal cheapestArea = new BigDecimal("100000");
            // 根据基准模版判断基准运费从哪个模版取值
            String bt = benchmarkTemplateType == null ? templateType : benchmarkTemplateType;
            for (String countryCode : countryCode32List) {
                BigDecimal cheapestAreaNew = getFreightByTemplateType(bt, countryCode, startWeight.toString());
                if (cheapestAreaNew != null && cheapestAreaNew.compareTo(new BigDecimal("0")) > 0) {
                    cheapestArea = cheapestArea.compareTo(cheapestAreaNew) > 0 ? cheapestAreaNew : cheapestArea;
                    System.out.println("******************" + countryCode + "=" + cheapestAreaNew + ",cheapest="
                            + cheapestArea + ",templateType=" + templateType);

                } else {
                    System.out.println("******************" + countryCode + "=" + cheapestAreaNew + ",cheapest="
                            + cheapestArea + ",templateType=" + templateType);
                }
            }
            if (cheapestArea.compareTo(new BigDecimal("100000")) >= 0) {
                // 如果大包专线的基准是标准或者特货标准，则没有2kg以上的计价，按2kg计价
                if ((benchmarkTemplateType.equals("1") || benchmarkTemplateType.equals("7")) && templateType.equals("4")) {
                    for (String countryCode : countryCode32List) {
                        cheapestArea = getFreightByTemplateType(bt, countryCode, "2000");
                    }
                } else {
                    // 运费路线不支持32个国家，抛异常
                    throw new RuntimeException();
                }
            }

            // 3、根据基准运费，获取价格差，相差为负数的忽略，相差为正数的，去该区间内每10g的运费
            //

            for (ErpProductFreight country : allCountryList) {
                if (country.getCountryCode().equals("DK")) {
                    System.out.println("******************test******************");
                }
                // 2、根据最低运费，计算基准运费：最便宜运费*1.1*1.5
                BigDecimal benchmarkFreight = cheapestArea.multiply(new BigDecimal("1.1"))
                        .multiply(new BigDecimal("1.5"));
                // 获取目的国真实运费
                BigDecimal countryFreight = getFreightByTemplateType(templateType, country.getCountryCode(),
                        startWeight.toString());
                if (countryFreight == null) {
                    // 说明不支持该线路
                    continue;
                } else {
                    // 上浮10%
                    countryFreight = countryFreight.multiply(new BigDecimal("1.1"));
                }

                // 如果基准模版不为空，则保留32个国家的运费差,否则去除32个国家
                if (benchmarkTemplateType == null) {
                    if (!countryCode32List.contains(country.getCountryCode())) {
                        // 加入map
                        if (!voMap.containsKey(country.getCountryCode())) {
                            vo = new ErpProductRefinementFreightVo();
                            vo.setCountry(country.getCountry());
                            vo.setCountryEn(country.getCountryEn());
                            vo.setCountryCode(country.getCountryCode());
                            voMap.put(country.getCountryCode(), vo);
                        }

                        // 获取上一轮真实运费和上一轮基准运费
                        if (previousFreightMap.containsKey(country.getCountryCode())) {
                            previousBenchmark = new BigDecimal(
                                    previousFreightMap.get(country.getCountryCode()).split(":")[0]);
                            previousActual = new BigDecimal(
                                    previousFreightMap.get(country.getCountryCode()).split(":")[1]);
                            previousFreightMap.put(country.getCountryCode(),
                                    benchmarkFreight.toString() + ":" + countryFreight);
                        } else {
                            previousFreightMap.put(country.getCountryCode(),
                                    benchmarkFreight.toString() + ":" + countryFreight);
                        }
                        // 补差的运费
                        BigDecimal makeupFreight = new BigDecimal("0");
                        // 先判断基准价和真实价格，如果基准价大于真实价格，无需补差额。根据差值获取每10g的运费：(真实-(上一轮真实-上一轮基准)-基准)/10，单位人民币，
                        if (countryFreight.compareTo(benchmarkFreight) > 0) {
                            if ((countryFreight.subtract(previousActual).add(previousBenchmark))
                                    .compareTo(benchmarkFreight) > 0) {
                                // 需要补差
                                makeupFreight = (countryFreight.subtract(previousActual).add(previousBenchmark)
                                        .subtract(benchmarkFreight)).divide(new BigDecimal("10"), 2,
                                        BigDecimal.ROUND_UP);
                                // 判断币种
                                if (currency.equals("USD")) {
                                    // 汇率统一按7算
                                    makeupFreight = makeupFreight.divide(new BigDecimal("7"), 2, BigDecimal.ROUND_UP);
                                }
                            }
                        }
                        // 输出
                        voMap.put(country.getCountryCode(),
                                compareFreight(voMap.get(country.getCountryCode()), startWeight, makeupFreight));
                    }
                } else {
                    if (templateType.equals("4")) {
                        // 如果参考运费模版为标准或者特货标准，则考虑计算2KG以下的差价问题
                        if (!benchmarkTemplateType.equals("1") && !benchmarkTemplateType.equals("7")) {
                            // 如果真实运费模版是标准大包，则考虑计泡问题。2100g以下，只计算不计泡的，2100g及以上，开始计算全部的
                            ErpProductFreightBale freightBale = baleMapper
                                    .getFreightTemplateByCountryCode(country.getCountryCode(), "菜鸟无忧物流-标准");
                            if (freightBale.getBubbleType().intValue() == 1
                                    && startWeight.compareTo(new BigDecimal("2100")) < 0) {
                                // 计泡 且小于2100，不计算
                                continue;
                            }
                        }

                    }

                    // 加入map
                    if (!voMap.containsKey(country.getCountryCode())) {
                        vo = new ErpProductRefinementFreightVo();
                        vo.setCountry(country.getCountry());
                        if (countryCode32List.contains(country.getCountryCode())) {
                            // 32个国家内，单独标注一下
                            vo.setCountry("***区域调价***" + country.getCountry());
                        }
                        vo.setCountryEn(country.getCountryEn());
                        vo.setCountryCode(country.getCountryCode());
                        voMap.put(country.getCountryCode(), vo);
                    }

                    // 基准模版不为空，则32个国家运费差为两种运费模版的差值。32个国家之外，为试算模版与基准模板的基准价的差
                    // 先计算32个国家的两个运费模版
                    if (countryCode32List.contains(country.getCountryCode())) {
                        // 获取真实模版运费
//						BigDecimal trialFreight = getFreightByTemplateType(templateType, country.getCountryCode(), startWeight.toString());
                        // 获取基准模版运费
                        BigDecimal bf = getFreightByTemplateType(benchmarkTemplateType, country.getCountryCode(),
                                startWeight.toString());
                        if (countryFreight != null && bf != null) {
                            // 两个模版都不为空，则计算两个模版的运费差
                            // 上浮10%
                            benchmarkFreight = bf.multiply(new BigDecimal("1.1"));
                        } else {
                            // 试算模版为空，无需计算，基准模板为空，则32个国家已经做了一口价，也无需计算
                            continue;
                        }
                    }
                    // 获取上一轮真实运费和上一轮基准运费(32个国家的基准运费等于基准模版的运费)
                    if (previousFreightMap.containsKey(country.getCountryCode())) {
                        previousBenchmark = new BigDecimal(
                                previousFreightMap.get(country.getCountryCode()).split(":")[0]);
                        previousActual = new BigDecimal(previousFreightMap.get(country.getCountryCode()).split(":")[1]);
                    } else {
                        previousBenchmark = new BigDecimal("0");
                        previousActual = new BigDecimal("0");
                    }
                    previousFreightMap.put(country.getCountryCode(),
                            benchmarkFreight.toString() + ":" + countryFreight);

                    // 补差的运费
                    BigDecimal makeupFreight = new BigDecimal("0");
                    // 先判断基准价和真实价格，如果基准价大于真实价格，无需补差额。根据差值获取每10g的运费：(真实-(上一轮真实-上一轮基准)-基准)/10，单位人民币，
                    if (countryFreight.compareTo(benchmarkFreight) > 0) {
                        if ((countryFreight.subtract(previousActual).add(previousBenchmark))
                                .compareTo(benchmarkFreight) > 0) {
                            // 需要补差
                            makeupFreight = (countryFreight.subtract(previousActual).add(previousBenchmark)
                                    .subtract(benchmarkFreight)).divide(new BigDecimal("10"), 2, BigDecimal.ROUND_UP);
                            // 判断币种
                            if (currency.equals("USD")) {
                                // 汇率统一按7算
                                makeupFreight = makeupFreight.divide(new BigDecimal("7"), 2, BigDecimal.ROUND_UP);
                            }
                        }
                    }
                    // 输出
                    voMap.put(country.getCountryCode(),
                            compareFreight(voMap.get(country.getCountryCode()), startWeight, makeupFreight));
                }
            }
            startWeight = startWeight.add(new BigDecimal("100"));
        }

        // 遍历组合
        for (String key : voMap.keySet()) {
            voList.add(voMap.get(key));
        }

        // 生成标准的运费模版
//		return createAEStandardShippingTemplate(voList, templateType);
        return voList;
    }

    /**
     * 根据精细化运费模版，生成标准的速卖通物流模板
     *
     * @param voList
     * @return
     */
    private List<AEProductRefinementFreightVo> createAEStandardShippingTemplate(
            List<ErpProductRefinementFreightVo> voList, String templateType) {
        AEProductRefinementFreightVo aeVo = null;
        List<AEProductRefinementFreightVo> aeVoList = new ArrayList<>();
        // 判断该物流模板是否省略了包邮线路，即国家名称中是否存在***区域调价***
        boolean omitFreeShippingCountry = true;
        List<String> countryList = voList.stream().map(e -> e.getCountry()).collect(Collectors.toList());
        for (String country : countryList) {
            if (country.contains("***区域调价***")) {
                omitFreeShippingCountry = false;
                break;
            }
        }
        // 循环精细化报表
        for (ErpProductRefinementFreightVo vo : voList) {
            aeVo = new AEProductRefinementFreightVo();
            // 获取国家中文名
            if (vo.getCountry().equals("中国香港特别行政区") || vo.getCountryCode().equals("HK")) {
                aeVo.setCountry("Hong Kong(China)");
            } else if (vo.getCountry().equals("中国台湾") || vo.getCountryCode().equals("TW")) {
                aeVo.setCountry("Taiwan(China)");
            } else if (vo.getCountry().equals("爱沙尼亚") || vo.getCountryCode().equals("EE")) {
                aeVo.setCountry("Estonia");
            } else if (vo.getCountry().equals("拉脱维亚") || vo.getCountryCode().equals("LV")) {
                aeVo.setCountry("Latvia");
            } else {
                aeVo.setCountry(vo.getCountry().contains("***区域调价***") ? vo.getCountry().replace("***区域调价***", "")
                        : vo.getCountry());
            }

            // 计费方式
            aeVo.setBillingMethod("按重量计费");

            // 续重次数
            int currentWeightRenewalTimes = 0;
            // 续重开始重量
            String startWeight = "0.001";
            /**
             * 根据f1-f200的数值，判断并设置首重和首重费用 1、若f1 > 0 ，首重为0.001kg，首重费用为f1 2、若f1 =
             * 0，首重为0.001kg，首重费用为f1 3、若f2 > 0, 续重为0.001kg，续重范围为f3及以后第一次出现不等于f2的范围
             */
            // 根据类型确定循环次数
            int cycles = (templateType.equals("3") || templateType.equals("4")) ? 201 : 21;
            loop1:
            for (int i = 1; i < cycles; i++) {
                String freight = "0";
                String nextfreight = "0";
                // 设置首重和首重费用
                if (i == 1) {
                    freight = getValue(vo, i + "");
                    aeVo.setFirstWeight("0.001");
                    aeVo.setFirstFreight(freight.equals("无数据") ? "0"
                            : new BigDecimal(freight).multiply(new BigDecimal("10")).toString());
                    continue loop1;
                }
                // 设置续重
                loop2:
                while (true) {
                    currentWeightRenewalTimes++;
                    freight = getValue(vo, i + "");
                    if (freight == null || freight.equals("无数据")) {
                        throw new RuntimeException();
                    } else if (new BigDecimal(freight).compareTo(new BigDecimal("0")) == 0) {
                        if (i < cycles) {
                            i++;
                            continue loop2;
                        } else {
                            break loop1;
                        }
                    }
                    // 算到有值为止
                    loop3:
                    while (true) {
                        // 判断下一列是否与该列数值相等
                        i++;
                        nextfreight = getValue(vo, i + "");
                        if (nextfreight == null || nextfreight.equals("无数据")) {
                            if (cycles <= (i + 1)) {
                                break loop2;
                            } else {
                                System.out.println(aeVo.getCountry() + " -- " + i);
                                throw new RuntimeException();
                            }
                        } else if (new BigDecimal(nextfreight).compareTo(new BigDecimal(freight)) == 0) {
                            // 如果下一列等于刚才的列，继续
                            if (i < cycles) {
                                i++;
                                continue loop3;
                            } else {
                                break loop1;
                            }
                        } else {
                            // 下一列不等于刚才的列，跳出续重循环
                            break loop2;
                        }
                    }
                }
                if (currentWeightRenewalTimes > 10) {
                    System.out.println(aeVo.getCountry() + " -- " + i);
                    throw new RuntimeException();
                }
                // 记录当前i值 比如i=3,说明续重到300g,i=11,说明续重到1100g
                // 设置续重范围
                setValue(aeVo, "ContinuationRange" + currentWeightRenewalTimes,
                        startWeight + "-" + new BigDecimal((i - 1) + "").divide(new BigDecimal("10")).toString());
//				aeVo.setContinuationRange1(startWeight + "-" + new BigDecimal(i+"").divide(new BigDecimal("10")).toString());
                startWeight = new BigDecimal((i - 1) + "").divide(new BigDecimal("10")).toString();
                // 设置续重范围1-每增加 (kg)
                setValue(aeVo, "Continuation" + currentWeightRenewalTimes, "0.1");
//				aeVo.setContinuation1("0.1");
                // 设置续重范围1-续加运费 (¥)
                setValue(aeVo, "ContinuationFreight" + currentWeightRenewalTimes,
                        new BigDecimal(freight).multiply(new BigDecimal("10")).toString());
//				aeVo.setContinuationFreight1(new BigDecimal(freight).multiply(new BigDecimal("10")).toString());

                aeVoList.add(aeVo);
            }
        }

        // 判断计价方式
        if (omitFreeShippingCountry) {
            aeVo = new AEProductRefinementFreightVo();
            // 省略包邮国家
            aeVo.setCountry("若不在以上国家/地区内");
            aeVo.setBillingMethod("卖家承担");
        } else {
            aeVo.setCountry("若不在以上国家/地区内");
            aeVo.setBillingMethod("不发货");
        }
        aeVoList.add(aeVo);
        return aeVoList;
    }

    /**
     * 运费试算-菜鸟标准普货、标准特货、菜鸟特货专线-标准 共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoStandard(ErpProductExistingFreightRecord productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");

        // 获取 菜鸟无忧物流-标准 的目的国的计价标准
        ErpProductFreight erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(),
                productFreight.getType(), productFreight.getWeight(), productFreight.getFreightType());

        if (erpProductFreight == null) {
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取获取 CR(哥斯达黎加) 的计价标准代替
                erpProductFreight = baseMapper.getFreightTemplateByCountryCode("CR", productFreight.getType(),
                        productFreight.getWeight(), "菜鸟无忧物流-标准");
                if (erpProductFreight == null) {
                    // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                    return freight;
                }
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        freight = erpProductFreight.getFreight().divide(new BigDecimal("1000"))
                .multiply(new BigDecimal(productFreight.getWeight()));
        return freight.add(erpProductFreight.getRegistrationFee());
    }

    /**
     * 运费试算-菜鸟标准普货、标准特货、菜鸟特货专线-标准 共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoStandard(AeProductFreight productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");

        // 获取 菜鸟无忧物流-标准 的目的国的计价标准
        ErpProductFreight erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(),
                productFreight.getType(), productFreight.getWeight(), productFreight.getFreightType());

        if (erpProductFreight == null) {
            System.out.println("****************" + productFreight.getCountry() + "*************************");
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取获取 CR(哥斯达黎加) 的计价标准代替
                erpProductFreight = baseMapper.getFreightTemplateByCountryCode("CR", productFreight.getType(),
                        productFreight.getWeight(), "菜鸟无忧物流-标准");
                if (erpProductFreight == null) {
                    // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                    return freight;
                }
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        freight = erpProductFreight.getFreight().divide(new BigDecimal("1000"))
                .multiply(new BigDecimal(productFreight.getWeight()));
        return freight.add(erpProductFreight.getRegistrationFee());
    }

    /**
     * 运费试算-菜鸟菜鸟超级经济Global、菜鸟专线经济、菜鸟特货专线－超级经济、菜鸟超级经济 共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoSuperEconomy(ErpProductExistingFreightRecord productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");
        if (productFreight.getCountry().equals("PH")) {
            System.out.println();
        }

        // 获取目的国的计价标准
        ErpProductFreightEconomy freightEconomy = economyMapper.getFreightTemplateByCountryCode(
                productFreight.getCountry(), null, productFreight.getWeight(), productFreight.getFreightType());

        if (freightEconomy == null) {
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取 菜鸟无忧物流标准 的计价标准或 菜鸟特货专线－标准 代替
                ErpProductFreight erpProductFreight = null;
                if (productFreight.getType().intValue() == 4) {
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), 0,
                            productFreight.getWeight(), "菜鸟无忧物流-标准");
                } else {
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), 1,
                            productFreight.getWeight(), "菜鸟特货专线－标准");
                }

                if (erpProductFreight == null) {
                    // 是运费试算，不允许为空，获取获取 CR(哥斯达黎加) 的计价标准代替
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode("CR", 0, productFreight.getWeight(),
                            "菜鸟无忧物流-标准");
                    if (erpProductFreight == null) {
                        // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                        return freight;
                    }
                }
                freight = erpProductFreight.getFreight().divide(new BigDecimal("1000"))
                        .multiply(new BigDecimal(productFreight.getWeight()));
                return freight.add(erpProductFreight.getRegistrationFee());
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        freight = freightEconomy.getFreight().divide(new BigDecimal("1000"))
                .multiply(new BigDecimal(productFreight.getWeight()));
        return freight.add(freightEconomy.getRegistrationFee());
    }

    /**
     * 运费试算-菜鸟菜鸟超级经济Global、菜鸟专线经济、菜鸟特货专线－超级经济、菜鸟超级经济 共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoSuperEconomy(AeProductFreight productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");
        if (productFreight.getCountry().equals("PH")) {
            System.out.println();
        }

        // 获取目的国的计价标准
        ErpProductFreightEconomy freightEconomy = economyMapper.getFreightTemplateByCountryCode(
                productFreight.getCountry(), null, productFreight.getWeight(), productFreight.getFreightType());

        if (freightEconomy == null) {
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取 菜鸟无忧物流标准 的计价标准或 菜鸟特货专线－标准 代替
                ErpProductFreight erpProductFreight = null;
                if (productFreight.getType().intValue() == 4) {
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), 0,
                            productFreight.getWeight(), "菜鸟无忧物流-标准");
                } else {
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), 1,
                            productFreight.getWeight(), "菜鸟特货专线－标准");
                }

                if (erpProductFreight == null) {
                    // 是运费试算，不允许为空，获取获取 CR(哥斯达黎加) 的计价标准代替
                    erpProductFreight = baseMapper.getFreightTemplateByCountryCode("CR", 0, productFreight.getWeight(),
                            "菜鸟无忧物流-标准");
                    if (erpProductFreight == null) {
                        // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                        return freight;
                    }
                }
                freight = erpProductFreight.getFreight().divide(new BigDecimal("1000"))
                        .multiply(new BigDecimal(productFreight.getWeight()));
                return freight.add(erpProductFreight.getRegistrationFee());
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        freight = freightEconomy.getFreight().divide(new BigDecimal("1000"))
                .multiply(new BigDecimal(productFreight.getWeight()));
        return freight.add(freightEconomy.getRegistrationFee());
    }

    /**
     * 运费试算-菜鸟标准大包、大包专线共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoHeavy(ErpProductExistingFreightRecord productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");

        // 默认国大包是否计泡
        boolean isBubbleFlg = false;

        // 获取大包中 菜鸟无忧-标准 到获取目的国的计价标准
        ErpProductFreightBale freightBale = baleMapper.getFreightTemplateByCountryCode(productFreight.getCountry(),
                productFreight.getFreightType());
        if (freightBale == null) {
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取标准物流的大包
                freightBale = baleMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), "菜鸟无忧物流-标准");
                if (freightBale == null) {
                    // 是运费试算，不允许为空，获取标准物流的AL(阿尔巴尼亚)的大包
                    freightBale = baleMapper.getFreightTemplateByCountryCode("AL", "菜鸟无忧物流-标准");
                    // 默认计泡
                    isBubbleFlg = true;
                    if (freightBale == null) {
                        // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                        return freight;
                    }
                }
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        // 货物实际重量
        BigDecimal packageWeight = new BigDecimal(productFreight.getWeight());
        // 1、判断该目的国是否计泡，主要是判断是否需要更改货物的最终重量
        if (freightBale.getBubbleType().intValue() == 1
                || (isBubbleFlg && freightBale.getBubbleType().intValue() == 0)) {
            // 计泡，则计算体积重 ：长(cm)*宽(cm)*高(cm)/8000
            BigDecimal volumeWeight = new BigDecimal(productFreight.getLength())
                    .multiply(new BigDecimal(productFreight.getWidth()))
                    .multiply(new BigDecimal(productFreight.getHeight())).divide(new BigDecimal("8000"));
            // 按g进行比较
            if (packageWeight.compareTo(volumeWeight.multiply(new BigDecimal("1000"))) < 0) {
                // 泡物，取体积重的大值
                packageWeight = volumeWeight.multiply(new BigDecimal("1000"));
            }
        }
        // 判断是否超重 TODO 暂不考虑超重

        // 2、判断该目的国是否有续重
        if (freightBale.getContinuationWeight().equals("0")) {
            // 无续重，则1g起重
            freight = freightBale.getFirstFreight().divide(new BigDecimal(freightBale.getFirstWeight()))
                    .multiply(packageWeight);
            // 总费用为运费+挂号费
            return freight.add(freightBale.getRegistrationFee());
        } else {
            /**
             * 有续重， 1、重量未超起重 2、超起重，未超续重 3、超起重，超续重，续重按整数计算
             */
            // 判断是否有挂号费
            BigDecimal registrationFee = freightBale.getRegistrationFee() == null ? new BigDecimal("0")
                    : freightBale.getRegistrationFee();
            if (packageWeight.compareTo(new BigDecimal(freightBale.getFirstWeight())) <= 0) {
                // 未超起重
                return freightBale.getFirstFreight().add(registrationFee);
            } else {
                // 超起重，获取剩余重量
                BigDecimal remainingWeight = packageWeight.subtract(new BigDecimal(freightBale.getFirstWeight()));
                // 根据续重，向上取整
                BigDecimal multiple = remainingWeight.divide(new BigDecimal(freightBale.getContinuationWeight()), 0,
                        BigDecimal.ROUND_UP);
                // 总费用=起重+续重*倍数+挂号
                return freightBale.getFirstFreight().add(freightBale.getContinuationFreight().multiply(multiple))
                        .add(registrationFee);
            }
        }
    }


    /**
     * 运费试算-菜鸟标准大包、大包专线共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByCainiaoHeavy(AeProductFreight productFreight) {
        /**
         * 如果是运费试算，则不能返回空，否则，可以返回空
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");

        // 默认国大包是否计泡
        boolean isBubbleFlg = false;

        // 获取大包中 菜鸟无忧-标准 到获取目的国的计价标准
        ErpProductFreightBale freightBale = baleMapper.getFreightTemplateByCountryCode(productFreight.getCountry(),
                productFreight.getFreightType());
        if (freightBale == null) {
            // 说明该线路不支持目的国，判断是否为运费试算
            if (productFreight.getIsTrial()) {
                // 是运费试算，不允许为空，获取标准物流的大包
                freightBale = baleMapper.getFreightTemplateByCountryCode(productFreight.getCountry(), "菜鸟无忧物流-标准");
                if (freightBale == null) {
                    // 是运费试算，不允许为空，获取标准物流的AL(阿尔巴尼亚)的大包
                    freightBale = baleMapper.getFreightTemplateByCountryCode("AL", "菜鸟无忧物流-标准");
                    // 默认计泡
                    isBubbleFlg = true;
                    if (freightBale == null) {
                        // 是运费试算，没有说明该线路不支持该国家，给一个很大的值，方便排查错误
                        return freight;
                    }
                }
            } else {
                // 是预估运费，没有说明该线路不支持该国家
                return null;
            }
        }
        // 货物实际重量
        BigDecimal packageWeight = new BigDecimal(productFreight.getWeight());
        // 1、判断该目的国是否计泡，主要是判断是否需要更改货物的最终重量
        if (freightBale.getBubbleType().intValue() == 1
                || (isBubbleFlg && freightBale.getBubbleType().intValue() == 0)) {
            // 计泡，则计算体积重 ：长(cm)*宽(cm)*高(cm)/8000
            BigDecimal volumeWeight = new BigDecimal(productFreight.getLength())
                    .multiply(new BigDecimal(productFreight.getWidth()))
                    .multiply(new BigDecimal(productFreight.getHeight())).divide(new BigDecimal("8000"));
            // 按g进行比较
            if (packageWeight.compareTo(volumeWeight.multiply(new BigDecimal("1000"))) < 0) {
                // 泡物，取体积重的大值
                packageWeight = volumeWeight.multiply(new BigDecimal("1000"));
            }
        }
        // 判断是否超重 TODO 暂不考虑超重

        // 2、判断该目的国是否有续重
        if (freightBale.getContinuationWeight().equals("0")) {
            // 无续重，则1g起重
            freight = freightBale.getFirstFreight().divide(new BigDecimal(freightBale.getFirstWeight()))
                    .multiply(packageWeight);
            // 总费用为运费+挂号费
            return freight.add(freightBale.getRegistrationFee());
        } else {
            /**
             * 有续重， 1、重量未超起重 2、超起重，未超续重 3、超起重，超续重，续重按整数计算
             */
            // 判断是否有挂号费
            BigDecimal registrationFee = freightBale.getRegistrationFee() == null ? new BigDecimal("0")
                    : freightBale.getRegistrationFee();
            if (packageWeight.compareTo(new BigDecimal(freightBale.getFirstWeight())) <= 0) {
                // 未超起重
                return freightBale.getFirstFreight().add(registrationFee);
            } else {
                // 超起重，获取剩余重量
                BigDecimal remainingWeight = packageWeight.subtract(new BigDecimal(freightBale.getFirstWeight()));
                // 根据续重，向上取整
                BigDecimal multiple = remainingWeight.divide(new BigDecimal(freightBale.getContinuationWeight()), 0,
                        BigDecimal.ROUND_UP);
                // 总费用=起重+续重*倍数+挂号
                return freightBale.getFirstFreight().add(freightBale.getContinuationFreight().multiply(multiple))
                        .add(registrationFee);
            }
        }
    }


    /**
     * 运费试算-燕文 共用
     *
     * @param productFreight
     * @return
     */
    @Override
    public BigDecimal freightCalculateByYanWen(ErpProductExistingFreightRecord productFreight) {
        /**
         * 燕文物流只在预估运费的时候使用
         */
        // 设置运费，默认大一些，方便出错及时发现
        BigDecimal freight = new BigDecimal("10000");
        BigDecimal registrationFee = new BigDecimal("0");

        // 获取 目的国的计价标准
        ErpProductFreightYanwen erpProductFreightYanwen = yanwenMapper.getFreightTemplateByCountryCode(
                productFreight.getCountry(), productFreight.getWeight(), null, productFreight.getFreightType());

        if (erpProductFreightYanwen == null) {
            // 预估运费，没有说明该线路不支持该国家
            return null;
        }
        /**
         * 几种情况说明 1、如果是澳大利亚，则需要根据区号获取运费 2、如果有续重，按续重规则来 3、如果没有续重，按正常规则来，注意首重
         */
        // 判断是否是澳大利亚
        if (erpProductFreightYanwen.getZone() != null) {
            if (productFreight.getZipCode() == null) {
                // 澳大利亚国家，但没有邮编，无法获取分区号，逻辑不对抛异常
                throw new RuntimeException();
            }
            // 根据邮编获取分区，并重新获取计价标准
            ErpProductFreightCountryZone countryZone = countryZoneMapper
                    .selectOne(new LambdaQueryWrapper<ErpProductFreightCountryZone>()
                            .eq(ErpProductFreightCountryZone::getZipCode, productFreight.getZipCode())
                            .eq(ErpProductFreightCountryZone::getLogisticsCompany, "燕文")
                            .eq(ErpProductFreightCountryZone::getCountry, "澳大利亚")
                            .eq(ErpProductFreightCountryZone::getRevision, "1"));
            erpProductFreightYanwen = yanwenMapper.getFreightTemplateByCountryCode(productFreight.getCountry(),
                    productFreight.getWeight(), countryZone.getZone(), productFreight.getFreightType());
        }
        BigDecimal packageWeight = new BigDecimal(productFreight.getWeight());
        BigDecimal firstWeight = erpProductFreightYanwen.getFirstFreight() == null ? new BigDecimal("0")
                : erpProductFreightYanwen.getFirstFreight();

        // 判断是否有续重
        if (erpProductFreightYanwen.getContinuationWeight() == null) {
            // 无续重，判断首重和实际重量大小，取大
            packageWeight = firstWeight.compareTo(packageWeight) > 0 ? firstWeight : packageWeight;
            freight = erpProductFreightYanwen.getFreight().divide(new BigDecimal("1000")).multiply(packageWeight);
            registrationFee = erpProductFreightYanwen.getRegistrationFee();
        } else {
            /**
             * 有续重， 1、重量未超起重 2、超起重，未超续重 3、超起重，超续重，续重按整数计算
             */
            // 判断是否有挂号费
            registrationFee = erpProductFreightYanwen.getRegistrationFee() == null ? new BigDecimal("0")
                    : erpProductFreightYanwen.getRegistrationFee();
            if (packageWeight.compareTo(firstWeight) <= 0) {
                // 未超起重
                freight = erpProductFreightYanwen.getFirstFreight();
            } else {
                // 超起重，获取剩余重量
                BigDecimal remainingWeight = packageWeight.subtract(firstWeight);
                // 根据续重，向上取整
                BigDecimal multiple = remainingWeight.divide(
                        new BigDecimal(erpProductFreightYanwen.getContinuationWeight()), 0, BigDecimal.ROUND_UP);
                // 运费=起重+续重*倍数
                freight = erpProductFreightYanwen.getFirstFreight()
                        .add(erpProductFreightYanwen.getContinuationFreight().multiply(multiple));
            }
        }
        return freight.add(registrationFee);
    }

    /**
     * 根据模版类型，获取相应运费
     *
     * @param templateType 1-标准普货，2-经济普货，3-标准大包，4-大包专线，5-标准特货，6-经济特货，7-特货专线-标准
     * @param countryCode
     * @param weight
     * @return
     */
    private BigDecimal getFreightByTemplateType(String templateType, String countryCode, String weight) {
        BigDecimal freight = new BigDecimal("0");
        BigDecimal freightSG = new BigDecimal("0");

        // 组合测试数据，通过尺寸，默认小包
        ErpProductExistingFreightRecord productFreight = new ErpProductExistingFreightRecord();
        productFreight.setCountry(countryCode);
        productFreight.setLength("30");
        productFreight.setWidth("20");
        productFreight.setHeight("10");
        productFreight.setWeight(weight);
        // 默认普货
        productFreight.setType(0);
        // 非运费试算
        productFreight.setIsTrial(false);
        switch (templateType) {
            case "1":
                // 标准普货
                productFreight.setFreightType("菜鸟无忧物流-标准");
                freight = freightCalculateByCainiaoStandard(productFreight);
                /** 以后再用 **/
//				// 标准普货，则查询标准普货、标准特货、特货专线-标准，取小
//				productFreight.setFreightType("菜鸟无忧物流-标准");
//				freight = freightCalculateByCainiaoStandard(productFreight);
//				// 标准特货
//				productFreight.setType(1);
//				freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 取小
//				freight = freightSG.compareTo(freight) > 0 ? freight : freight;
//				// 特货专线-标准
//				productFreight.setFreightType("菜鸟特货专线－标准");
//				freightSG = freightCalculateByCainiaoStandard(productFreight);
//				// 取小
//				freight = freightSG.compareTo(freight) > 0 ? freight : freight;
                /** 以后再用 **/
                break;
            case "2":
                // 经济普货
                productFreight.setFreightType("菜鸟超级经济Global");
                freight = freightCalculateByCainiaoSuperEconomy(productFreight);
                /** 以后再用 **/
//				// 经济普货，则查询经济普货和经济特货，取小
//				productFreight.setFreightType("菜鸟超级经济Global");
//				freight = freightCalculateByCainiaoSuperEconomy(productFreight);
//				// 经济特货
//				productFreight.setFreightType("菜鸟特货专线－超级经济");
//				freightSG = freightCalculateByCainiaoSuperEconomy(productFreight);
//				freight = freightSG.compareTo(freight) > 0 ? freight : freight;
                /** 以后再用 **/
                break;
            case "3":
                // 标准大包
                productFreight.setLength("63");
                productFreight.setFreightType("菜鸟无忧物流-标准");
                freight = freightCalculateByCainiaoHeavy(productFreight);
                break;
            case "4":
                // 大包专线
                productFreight.setLength("63");
                productFreight.setFreightType("菜鸟大包专线");
                freight = freightCalculateByCainiaoHeavy(productFreight);
                break;
            case "5":
                // 标准特货
                productFreight.setType(1);
                productFreight.setFreightType("菜鸟无忧物流-标准");
                freight = freightCalculateByCainiaoStandard(productFreight);
                break;
            case "6":
                // 经济特货
                productFreight.setFreightType("菜鸟特货专线－超级经济");
                freight = freightCalculateByCainiaoSuperEconomy(productFreight);
                break;
            case "7":
                // 特货专线-标准
                productFreight.setType(1);
                productFreight.setFreightType("菜鸟特货专线－标准");
                freight = freightCalculateByCainiaoStandard(productFreight);
                break;
            case "8":
                // 特货专线-标准
                productFreight.setType(1);
                productFreight.setFreightType("菜鸟特货专线-标快");
                freight = freightCalculateByCainiaoStandard(productFreight);
                break;
            default:
                // 抛异常，防止发生错误
                throw new RuntimeException();
        }
        return freight;
    }

    /**
     * 动态调用实体的set方法
     *
     * @param dto   实体
     * @param name  动态拼接字段
     * @param value 值
     * @throws Exception
     */
    private void setValue(Object dto, String name, Object value) {
        try {
            Method[] m = dto.getClass().getMethods();
            for (int i = 0; i < m.length; i++) {
                if (("set" + name).toLowerCase().equals(m[i].getName().toLowerCase())) {
                    m[i].invoke(dto, value);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 动态给实体类属性赋值
     *
     * @param vo
     * @param startWeight
     * @param makeupFreight
     * @return
     */
    private ErpProductRefinementFreightVo compareFreight(ErpProductRefinementFreightVo vo, BigDecimal startWeight,
                                                         BigDecimal makeupFreight) {
        setValue(vo, "F" + startWeight.divide(new BigDecimal("100"), 0, BigDecimal.ROUND_DOWN).toString(),
                makeupFreight);
        return vo;
    }

    /**
     * 动态调用实体的get方法(注意返回值)
     *
     * @param dto  实体
     * @param name 动态拼接字段
     * @return
     **/
    private String getValue(Object dto, String name) {
        String val = "无数据";
        try {
            if (StringUtils.isEmpty(name))
                return val;
            Method m = dto.getClass().getMethod(("getF" + name));
            // 调用getter方法获取属性值
            // java.math.BigDecimal类型转换
            if (m.getGenericReturnType().equals(BigDecimal.class)) {
                if (m.invoke(dto) == null) {
                    return "无数据";
                }
                String format = m.invoke(dto).toString();
                val = null == format ? "无数据" : format;
            } else {
                val = StringUtils.isNotEmpty((String) m.invoke(dto)) ? (String) m.invoke(dto) : "无数据";
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return val;
    }

    public static void main(String[] args) {
        System.out.println(new BigDecimal("32100").divide(new BigDecimal("100"), 0, BigDecimal.ROUND_DOWN).toString());
    }
}
